package cn.spring.framework.redis.core.redis;

import cn.hutool.core.util.StrUtil;
import cn.spring.framework.redis.config.LzmhRedisProperties;
import cn.spring.framework.redis.constant.Constants;
import cn.spring.framework.redis.core.FillCache;
import cn.spring.framework.redis.core.Refresher;
import cn.spring.framework.redis.core.StringOperator;
import cn.spring.framework.redis.excutor.AsyncCacheExecutor;
import cn.spring.framework.redis.excutor.CacheExecutor;
import cn.spring.framework.redis.excutor.FutureAdapter;
import cn.spring.framework.redis.excutor.SyncCacheExecutor;
import cn.spring.framework.redis.service.RedisService;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author xingkong
 * @Title: RedisStringOperator
 * @Description: string类型操作实现
 * @date 2021/11/12 17:11
 */
public class RedisStringOperator extends AbstractRedisOperator implements StringOperator {
    /**
     * 异步任务执行器
     */
    protected CacheExecutor<String> asyncCacheExecutor = new AsyncCacheExecutor<>();

    public RedisStringOperator(LzmhRedisProperties lzmhRedisProperties, RedisService redisService) {
        super(lzmhRedisProperties, redisService);
    }

    @Override
    public String get(String key, long expire, Refresher<String> flusher) {
        return this.get(key, expire, flusher, new SyncCacheExecutor<>()).getData();
    }

    private FutureAdapter<String> get(String key, long expire,
                                      Refresher<String> flusher,
                                      CacheExecutor<String> cacheExecutor) {
        String res = redisService.getCacheObject(key);

        if (StrUtil.isNotEmpty(res)) {
            return FutureAdapter.runAndGetFuture(res);
        }

        //缓存过期，则重新刷新缓存
        return (FutureAdapter<String>) cacheExecutor.executor(() -> this.fillCache(new FillCache<String>() {
            @Override
            public String getKey() {
                return key;
            }

            @Override
            public String getIgnoreValidData() {
                return (String) blockIfNeed(this.getKey());
            }

            @Override
            public String getCacheData() {
                //执行具体的获取缓存数据逻辑
                String data = flusher.refresh();
                //对过期时间进行延长
                if (expire != Constants.REDIS_TTL_FOREVER) {
                    long newExpire = getExtendExpire(expire);
                    //填充缓存
                    redisService.setCacheObject(this.getKey(), data, newExpire, TimeUnit.SECONDS);
                }
                //填充缓存
                redisService.setCacheObject(this.getKey(), data);

                return data;
            }
        }));

    }

    @Override
    public Future<String> getAsync(String key, long expire, Refresher<String> flusher) {
        return this.get(key, expire, flusher, this.asyncCacheExecutor);
    }

    @Override
    public Future<String> getAsync(String key, long expire, Refresher<String> flusher, ExecutorService executorService) {
        return this.get(key, expire, flusher, new AsyncCacheExecutor<>(executorService));
    }

    @Override
    public void del(String key) {
        redisService.deleteObject(key);
    }

    @Override
    protected Object getDataIgnoreValid(String key) {
        return redisService.<String>getCacheObject(key);
    }
}
